//
//  MeshTool.m
//  FDSMeshLibDemo
//
//  Created by LEIPENG on 2022/5/31.
//

#import "MeshTool.h"
#import <CommonCrypto/CommonCryptor.h>

#define SAVE_LOG   @"SAVE_LOG"
#define FDS_APP_ID @"185BD3FB2532A7CE6BF4B2C15B8C27F06E0554779140BF726A929128FD0514BE"

@implementation MeshTool

+ (id)shareInstance{
    static MeshTool *meshTool =  nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        meshTool = [[MeshTool alloc] init];
    });
    return meshTool;
}

- (id)init{
    if (self = [super init]) {
        [self Initialize];
    }
    return self;
}

#pragma mark - 初始化
- (void)Initialize{
    // 初始化SDK
    [FDSMeshApi startWithAppId:FDS_APP_ID];
    // 获取SDK版本
    NSString *version = [FDSMeshApi getVersion];
    // 配置日志
    [FDSMeshApi openSdkLog:YES];
    // 配置连接参数
    [FDSMeshApi configConnectParams:70.0 serviceTimeout:20.0 retryCount:2];
    // 初始化数组
    self.meshModel = [self getMeshModel];
    self.nodeList = [NSMutableArray array];
    self.groupList = [NSMutableArray array];
    self.nodeListWhitOutGroup = [NSMutableArray array];
    BOOL isClearLog = NO;
    if (self.meshModel.sdkVersion && self.meshModel.sdkVersion.length) {
        if ([version compare:self.meshModel.sdkVersion] == NSOrderedDescending) {
            isClearLog = YES;
        }
    } else {
        isClearLog = YES;
    }
    if (isClearLog) {
        [FDSMeshApi clearSdkLog];
    }
    self.meshModel.sdkVersion = version;
    [self codingMeshData:self.meshModel];
}

#pragma mark - 刷新节点和组
- (void)refreshNodesAndGroups{
    [FDSMeshApi refreshNodesAndGroups];
    [self.nodeList setArray:[FDSMeshApi getNodes]];
    [self.groupList setArray:[FDSMeshApi getGroups]];
    [self.nodeListWhitOutGroup setArray:[FDSMeshApi getNodesWhitOutGroup]];
}

#pragma mark - 发送数据
- (void)sendMessageAddress:(UInt16)address sendData:(NSData *)sendData isResponse:(BOOL)isResponse completion:(void (^)(NSData *responseData))completion{
    [FDSMeshApi sendMessageAddress:address sendData:sendData opcode:0xf0 vendorId:0x0211 responseMax:isResponse?1:0 responseOpcode:isResponse?0xf1:0xf0 retryCount:0 completion:completion];
}

#pragma mark - 数据归档
- (MeshModel *)getMeshModel{
    MeshModel *model = [self unCodeingMeshData];
    if (nil == model) {
        MeshStudioModel *studioModel = [[MeshStudioModel alloc] init];
        NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
        dateFormatter.dateFormat=@"yyyy-MM-dd HH:mm:ss";
        studioModel.title = @"studio-1";
        studioModel.subTitle = [dateFormatter stringFromDate:[NSDate date]];
        studioModel.meshJson = [FDSMeshApi getInitMeshJson];
        MeshModel *creatModel = [[MeshModel alloc] init];
        creatModel.isFastProvision = NO;
        creatModel.isCompatibleSubscribe = NO;
        creatModel.studioList = @[studioModel];
        [self codingMeshData:creatModel];
        return creatModel;
    } else {
        return model;
    }
}
- (MeshStudioModel *)getMeshStudioModel:(NSString *)title{
    NSString *meshJson = [FDSMeshApi getInitMeshJson];
    MeshStudioModel *studioModel = [[MeshStudioModel alloc] init];
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    dateFormatter.dateFormat=@"yyyy-MM-dd HH:mm:ss";
    studioModel.title = title;
    studioModel.subTitle = [dateFormatter stringFromDate:[NSDate date]];
    studioModel.meshJson = meshJson;
    return studioModel;
}
- (void)codingMeshData:(MeshModel *)meshModel{
    NSString * dataPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject];
    NSString * dataPathName = [dataPath stringByAppendingString:@"/FDS_MeshData.data"];
    [NSKeyedArchiver archiveRootObject:meshModel toFile:dataPathName];
}
- (MeshModel *)unCodeingMeshData{
    NSString * dataPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject];
    NSString * dataPathName = [dataPath stringByAppendingString:@"/FDS_MeshData.data"];
    MeshModel *meshModel = [NSKeyedUnarchiver unarchiveObjectWithFile:dataPathName];
    return meshModel;
}

#pragma mark - Json字符串转字典
+ (NSDictionary *)jsonStringToDic:(NSString *)jsonString{
    if (jsonString == nil) {
        return nil;
    }
    NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
    NSError *err;
    NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData
                                                        options:NSJSONReadingMutableContainers
                                                          error:&err];
    if(err){
        return nil;
    }
    return dic;
}
+ (id)jsonStringToObj:(NSString *)jsonString{
    if (jsonString == nil) {
        return nil;
    }
    NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
    NSError *err;
    id obj = [NSJSONSerialization JSONObjectWithData:jsonData
                                                        options:NSJSONReadingMutableContainers
                                                          error:&err];
    if(err){
        return nil;
    }
    return obj;
}

+ (NSString *)textFromBase64String:(NSString *)base64 {
    NSString *key = @"com.telink.TelinkSDKMeshJsonData";
    NSData *data = [MeshTool dataWithBase64EncodedString:base64];
    //IOS 自带DES解密 Begin    改动了此处
    data = [MeshTool DESDecrypt:data WithKey:key];
    //IOS 自带DES加密 End
    return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}
+ (NSData *)DESDecrypt:(NSData *)data WithKey:(NSString *)key {
    char keyPtr[kCCKeySizeAES256+1];
    bzero(keyPtr, sizeof(keyPtr));

    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

    NSUInteger dataLength = [data length];

    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);

    size_t numBytesDecrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmDES, kCCOptionPKCS7Padding | kCCOptionECBMode, keyPtr, kCCBlockSizeDES, NULL, [data bytes], dataLength, buffer, bufferSize, &numBytesDecrypted);

    if (cryptStatus == kCCSuccess) {
        return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
    }

    free(buffer);
    return nil;
}
static const char encodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ (NSData *)dataWithBase64EncodedString:(NSString *)string {
    if (string == nil)
        [NSException raise:NSInvalidArgumentException format:@""];
    if ([string length] == 0)
        return [NSData data];

    static char *decodingTable = NULL;
    if (decodingTable == NULL) {
        decodingTable = malloc(256);
        if (decodingTable == NULL)
            return nil;
        memset(decodingTable, CHAR_MAX, 256);
        NSUInteger i;
        for (i = 0; i < 64; i++)
            decodingTable[(short)encodingTable[i]] = i;
    }

    const char *characters = [string cStringUsingEncoding:NSASCIIStringEncoding];
    if (characters == NULL)     //  Not an ASCII string!
        return nil;
    char *bytes = malloc((([string length] + 3) / 4) * 3);
    if (bytes == NULL)
        return nil;
    NSUInteger length = 0;

    NSUInteger i = 0;
    while (YES) {
        char buffer[4];
        short bufferLength;
        for (bufferLength = 0; bufferLength < 4; i++) {
            if (characters[i] == '\0')
                break;
            if (isspace(characters[i]) || characters[i] == '=')
                continue;
            buffer[bufferLength] = decodingTable[(short)characters[i]];
            if (buffer[bufferLength++] == CHAR_MAX) {
                // Illegal character!
                free(bytes);
                return nil;
            }
        }

        if (bufferLength == 0)
            break;
        if (bufferLength == 1) {
            //  At least two characters are needed to produce one byte!
            free(bytes);
            return nil;
        }

        //  Decode the characters in the buffer to bytes.
        bytes[length++] = (buffer[0] << 2) | (buffer[1] >> 4);
        if (bufferLength > 2)
            bytes[length++] = (buffer[1] << 4) | (buffer[2] >> 2);
        if (bufferLength > 3)
            bytes[length++] = (buffer[2] << 6) | buffer[3];
    }

    bytes = realloc(bytes, length);
    return [NSData dataWithBytesNoCopy:bytes length:length];
}

@end
